package shingling;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.StringTokenizer;

import org.tartarus.snowball.ext.PorterStemmer;

import weka.core.Stopwords;

public class shingling {

	
	/*
	 * Stopwords removed and shingles list<List<String>> created and returned 
	 */
	public List<List<String>> shingles(String param1, int k,boolean stem){
		
		PorterStemmer stemmer=new PorterStemmer();
		 
		StringBuffer buf=new StringBuffer();
		StringTokenizer stt=new StringTokenizer(param1);
		while(stt.hasMoreTokens()){
			String token=stt.nextToken();
			if(!Stopwords.isStopword(token)){
				
				if(stem){
					stemmer.setCurrent(token);
					stemmer.stem();
					buf.append(stemmer.getCurrent()+" ");
				}
				else{
					buf.append(token+" ");
				}
				
			}
		}
		
		String param2=buf.toString().toLowerCase();
		
		
		List<List<String>> shingles=new ArrayList<List<String>>();
		
		
		StringTokenizer tokens = new StringTokenizer(param2);
		List<String> temp=new ArrayList<String>();
		int i=0;
		int index=0;
		while(tokens.hasMoreTokens()){
			
			if(i++<k){
				temp.add(tokens.nextToken());
				
			}
			
			else{
				if(index==0)shingles.add(temp);
				
				
				
				shingles.add(new ArrayList<String>());
				index++;
				
				List<String> local=shingles.get(index-1);
				
				boolean flag=true;
				for(String key:local){
					
					if(flag){
						flag=!flag;
						continue;
					}
					else{
						
						shingles.get(index).add(key);
					}
				}
				shingles.get(index).add(tokens.nextToken());
				
			}
			
		}
		
		if (index==0)
			shingles.add(temp);
		
		return shingles;
		
	}
	

	
	
	public HashMap<Integer,Float> assignWeightShingles(HashMap<Integer,String> abc){
		
		HashMap<Integer,Float> weight=new HashMap<Integer,Float>();
		
		for(Integer l1:abc.keySet()){
			String str=abc.get(l1);
			System.err.println(str.toString());
			weight.put(l1,weight(str.toString(),true));
		}
		return weight;		
	}
	
	
	public float weight(String str,boolean location){
		
		float weight=0;
		if(location){
			//shingle contains a location then weight it more
			if(checkLocation.location.checkLocationGWS(str)){
				weight=10;
			}
		}
		else
			weight=2;
		
		return weight;
	}
	
	
	/*
	 * returns a hashMap of the hash list for the shingles
	 */
	public HashMap<Integer,String> hashList(List<List<String>> param1){
		
		
		HashMap<Integer,String> map=new HashMap<Integer,String>();
		
		for(List<String> abc:param1){
			int temp=abc.toString().hashCode();
			map.put(temp,abc.toString() );			
		}
		
		return map;
	}
	
	
	/*
	 * calculate jaccard similarity between shingles based upon content and weight given to shingles containing the same location..
	 * Location preference
	 * 
	 */
	public float jaccardSimilarityShingles(HashMap<Integer,String> h1,HashMap<Integer,String> h2){
		float relevance=0;
		
		List<Integer> s1=new ArrayList<Integer>();
		s1.addAll(h1.keySet());
		List<Integer> s2=new ArrayList<Integer>();
		s2.addAll(h2.keySet());
			
			HashMap<Integer, Integer> similarity=new HashMap<Integer, Integer>();			
			List<Integer> matchingShingles=new ArrayList<Integer>();
			
			
			int totalCount=0;
			
			for (int l1:s1){
				if(!similarity.containsKey(l1)){
					similarity.put(l1, 1);
					totalCount++;
				}
			}
			
			
			for (int l1:s2){
				if(similarity.containsKey(l1)){
					matchingShingles.add(l1);														
				}
				else
					totalCount++;
			}
			
			
			for(Integer match:matchingShingles){
			
				String temp=h1.get(match).toString().replace(',', ' ').replace('[', ' ').trim();
				temp=temp.substring(0,temp.length()-1);
				boolean flag=false;
				String arr[]=temp.split(" ");			
				for(String tt:arr){
					if(checkLocation.location.checkLocationQpUs(tt)){						
						relevance+=10;
			
						flag=true;
						break;						
					}
				}
				
				if(!flag)
					relevance+=3;
			}
			float unionh1h2=relevance+(totalCount-matchingShingles.size());
			
		return relevance/unionh1h2;
		
	}
	
	
	/*
	 * calculate jaccard similarity based upon simple hash values..
	 */
	public float jaccardSimilarity(HashMap<Integer,String> h1,HashMap<Integer,String> h2){
		
		List<Integer> s1=new ArrayList<Integer>();
		s1.addAll(h1.keySet());
		List<Integer> s2=new ArrayList<Integer>();
		s2.addAll(h2.keySet());
	
			
			HashMap<Integer, Integer> similarity=new HashMap<Integer, Integer>();			
			
			int sim=0;
			int totalCount=0;
			
			
			for (Integer l1:s1){				
				
				
				if(!similarity.containsKey(l1)){
					similarity.put(l1, 1);
					totalCount++;
				}
			}
			
			
			for (Integer l1:s2){				
				
				
				if(similarity.containsKey(l1)){
					sim++;														
				}
				else{				
					totalCount++;
				}
			}
			
			return((float)sim/totalCount);
			
	}
	
	
	
	public static List<List<Double>>  minHash(ArrayList<HashMap<Integer,String>> param1,int iterations){
		

		
		Set<Integer> ll=new HashSet<Integer>();
		for(HashMap<Integer,String> set1:param1){
			ll.addAll(set1.keySet());			
		}
		
		
		List<List<Double>> sim=new ArrayList<List<Double>>();
		
		for(int j=0;j<param1.size();j++){
			sim.add(new ArrayList<Double>());
			for(int k=0;k<param1.size();k++){
				sim.get(j).add(0d);
			}
		}
		
		
		
		
		Random obj1=new Random();
		
		for(int count=0;count<iterations;count++){

			HashMap<Integer,Integer> Mapping= new HashMap<Integer,Integer>();
			
			Set<Integer> out=new HashSet<Integer>();		
			
			for(int i:ll){
				int to;
				boolean flag=true;
				do{
					to=obj1.nextInt();
					if(!out.contains(to))flag=false;
				}while(flag);
				Mapping.put(i,to);
			}
			
			
			HashMap<Integer,ArrayList<Integer>> minHash=new HashMap<Integer,ArrayList<Integer>>();
			
			for(int index=0;index<param1.size();index++){
				
				HashMap<Integer,String> set1=param1.get(index);
				List<Integer> temp=new ArrayList<Integer>();
				temp.addAll(set1.keySet());
				int obj2=minValue(temp,Mapping);
				if(!minHash.keySet().contains(obj2)){
					minHash.put(obj2, new ArrayList<Integer>());
				}
				minHash.get(obj2).add(index);
			}
			
			
			
			Iterator itr= minHash.keySet().iterator();
			while(itr.hasNext()){
				Integer key=(Integer)itr.next();
				ArrayList<Integer> list=minHash.get(key);
				for(int id:list){
					for(int index=0;index<param1.size();index++){
						
						if(list.contains(index)){
							
							double temp=sim.get(id).get(index)*(count);
							temp+=1;
							temp/=(count+1);
							sim.get(id).set(index, temp);
						}
						else
						{
							double temp=sim.get(id).get(index)*(count);
							
							temp/=(count+1);
							sim.get(id).set(index, temp);
							
						}
						
					}
				}
			}
			
			

		}
		return sim;
		
	}
	
	public static  int minValue(List<Integer> ll,HashMap<Integer,Integer> perm){
		int min=Integer.MAX_VALUE;
		for(int key:ll){
			if(perm.get(key)<min){
				min=perm.get(key);
			}
		}
		
		return min;
	}
	public static boolean checkStopwords(String param1){
		boolean flag=false;
		flag=Stopwords.isStopword(param1);
		return flag;
	}
	
	
}
